package main

//cool "awesomeProject/testpackage"
import (
	"awesomeProject/dog"
	. "awesomeProject/testpackage"
	"fmt"
	"strconv"
)

// 函数内部不可声明函数 匿名函数可以
func main() {
	//demo11()
	demo112()
	//demo12()
	//demo13()
	//demo14()
	//demo15()
	//demo11Lianxi()
}

// 指针和地址
func demo8() {
	fmt.Println("********** 指针变量 *******************")
	var a int
	a = 123
	// 声明一个指针变量 *类型
	var b *int
	b = &a   // 指针变量只可以赋值 地址 &a
	*b = 999 // 指针变量赋值值 需要 *b = 值
	fmt.Println(a, b, *b, &a)

	fmt.Println("*********** 数组变量 演示指针 *******************")
	arr2222 := [1]string{"2,3,4"}
	var arrP *[1]string
	arrP = &arr2222
	// 修改arrP的下标0 的值为a
	// *arpp 拿取的是指针 需要加个()才可以拿到下文
	(*arrP)[0] = "a"

	// 修改arrp的变量
	fmt.Println(arr2222, arrP)

	fmt.Println("*********** 指针数组 *******************")
	// 数组指针 数组里面放的是指针
	var arrpp [3]*string
	str1 := "str1"
	str2 := "str2"
	str3 := "str3"
	arrpp = [3]*string{&str1, &str2, &str3}
	*arrpp[2] = "333333333"
	fmt.Println(arrpp, str2, str3)

	fmt.Println("***************** 指针参数 **********************")
	s := "2222"
	fmt.Println(s)
	pointFun(&s)
	fmt.Println(s)
}

// p1 指针参数
func pointFun(p1 *string) {
	*p1 = "顶顶顶顶顶顶顶顶顶顶"
}

// func 函数
func demo7() {
	// 关键词 defer表示延迟执行 表示会当前执行结构最后面执行
	defer t5()
	fmt.Println("调用函数 声明了返回参数名和类型")
	v1, v2 := t2(2, "dd")
	fmt.Println(v1, v2)

	fmt.Println("调用函数 声明了返回类型")
	v1, v2 = t1(3, "dd444444444")
	fmt.Println(v1, v2)

	fmt.Println("调用函数 匿名函数")
	b := func(data string) {
		fmt.Println(data)
	}

	b("hello world")

	fmt.Println("调用函数 不定性参数")
	t3(9527, "1", "2", "3")

	fmt.Println("调用函数 不定性参数 传参")
	ar := []string{"1", "2", "3"}
	t3(0000, ar...)

	fmt.Println("自执行函数")
	(func() {
		fmt.Println("自执行函数")
	})()

	fmt.Println("闭包函数调用")
	t4()(6)
}

// 需要返回
func t1(v1 int, v2 string) (int, string) {
	return v1, v2
}

// func 函数 大写表示共享 小写表示私有
func t2(v1 int, v2 string) (ret1 int, ret2 string) {
	// 如果定义了返回类型及变量名 这里声明了 那么直接return 就会返回
	ret1 = v1
	ret2 = v2
	return
}

// 不定性参数 必须要放在最后一位
func t3(data1 int, data2 ...string) {
	fmt.Println(data1, data2)
	for k, v := range data2 {
		fmt.Println(k, v)
	}
}

// 闭包函数 返回类型为 func (传递的参数类型)
func t4() func(int) {
	return func(num int) {
		fmt.Println("闭包函数执行 打印值为:", num)
	}
}

// 函数
func t5() {
	fmt.Println("........... 最先调用的函数 .............")
}

// map
func demo6() {
	fmt.Println("--------- map用途 -----------------")
	// 方式1
	var m map[string]string
	m = map[string]string{} // 需要初始化值
	m["name"] = "qm"
	m["age"] = "18岁"
	fmt.Println(m)

	// 方式2
	m1 := map[string]string{}
	m1["age"] = "男"
	fmt.Println(m1)

	// 方式3
	m2 := make(map[string]string)
	m2["sex"] = "18岁"
	fmt.Println(m2)

	m11 := map[int]bool{}
	m11[1] = true
	m11[2] = false
	fmt.Println(m11)

	// 空接口 任意类型和值
	fmt.Println("********** map 空接口 任意类型 ****************")
	m22 := map[int]interface{}{}
	m22[1] = 2222
	m22[2] = true
	m22[3] = [3]int{1, 2, 3}
	m22[4] = [...]int{1, 2, 3}
	m22[5] = []int{1, 2, 3}
	m22[6] = make([]int, 3)
	fmt.Println(m22, len(m22))

	fmt.Println("********** map 使用 ****************")
	delete(m22, 1)
	fmt.Println(m22, len(m22))

	fmt.Println("********** map 循环 ****************")
	fmt.Println(m22[3]) //  for range
	for k, v := range m22 {
		fmt.Println(k, v)
	}

	m33 := map[string]interface{}{}
	m33["name"] = true
	m33["age"] = 18
	fmt.Println(m33, m33["age"])
}

// 数组
func demo5() {
	a := [3]int{0, 1, 2}
	// [元素长度]元素类型{元素1,元素2,...}
	fmt.Println(a)

	// 动态可扩展
	b := [...]int{0, 1, 2}
	fmt.Println(b)

	// 默认值为0填充 但是会有长度限制
	var d = new([10]int)
	d[5] = 3
	fmt.Println(d)
	// len 长度 cap 容量
	fmt.Println(len(d), cap(d))

	// for循环迭代数组
	for i := 0; i < len(d); i++ {
		fmt.Println(d[i])
	}
	for i, v := range d {
		fmt.Println(i, v)
	}

	// 二维数组
	er := [2][3]int{
		{1, 2, 3},
		{2, 3, 4},
	}
	fmt.Println(er)

	fmt.Println("***************** cap len ***************")

	// 上面介绍都是固定的数组 超过长度就会报错

	fmt.Println("***************** 切片 数组 ***************")
	// 数组切片
	a11 := [3]int{0, 1, 2}
	// [起始索引:长度]
	c1 := a11[2:]
	c2 := a11[1:2]
	fmt.Println(c1, c2)
	// 用切片后 直接赋值指定索引会影响到原数组
	//c2[1] = 10
	// 不要直接指定索引赋值 否则 往后面加 可能会报错
	c2 = append(c2, 15)
	fmt.Println(a11, c2)

	fmt.Println("***************** 切片 copy ***************")
	a22 := [3]int{0, 1, 2}
	c22 := a22[:]
	c23 := a22[2:]
	c23 = append(c23, 15)
	c23 = append(c23, 66)
	// 通过copy函数可以把一个切片内容复制到另一个切片中 目标切片 源切片
	copy(c22, c23)
	fmt.Println(c22)

	fmt.Println("定义不受长度限制的数组")
	var aaa []int
	aaa = append(aaa, 2)
	fmt.Println(aaa)

	// make []int 5 len 可选参数cap make里面会默认填充0
	aaa1 := make([]int, 5)
	aaa1 = append(aaa1, 2)
	fmt.Println(aaa1)
}

// 流程控制
func demo4() {
	var num1 int = 80
	num1++
	fmt.Println(num1)

	if num1 < 100 {
		fmt.Println("小于100")
	} else if num1 < 120 {
		fmt.Println("小于120")
	} else {
		fmt.Println("大于20")
	}

	var type1 int = 2
	switch type1 {
	case 1:
		fmt.Println("111")
	case 2:
		fmt.Println("2222")
		fallthrough // 表示执行下一分支
	case 3:
		fmt.Println("333")
	case 4:
		fmt.Println("444")
	default:
		fmt.Println("other")
	}

	// 循环
	fmt.Println("********** 循环开始 ***************")
	//for i := 0; i < 10; i++ {
	//	fmt.Println(i)
	//}

	fmt.Println("********** a ***************")
	a := 1
	for {
		a++
		if a > 10 {
			break
		}
		fmt.Println(a)
	}

	fmt.Println("********** b ***************")
	b := 1
	for b < 10 {
		b++
		fmt.Println(b)
	}

	// 跳转语句
A:
	for i := 0; i < 10; i++ {
		if i > 3 {
			break A
			goto B
		}
	}
	fmt.Println("A end")
B:
	fmt.Println("goto b")
}

// 第三节 类型
func demo3() {
	// 第三节 数据类型
	// 整型
	var num1 uint // uint表示正整数 uint8 0-255
	var num2 int  // 表示 整数 包含负的 int8 -127 - 127
	//num1 = -999 报错必须是正整数
	num1 = 999
	num2 = 999
	fmt.Println(num1, num2)

	// 浮点类型 float64
	var num3 float32
	num3 = 3.14151679899912456
	fmt.Println(num3)

	// 加上双引号就是字符串
	str := "dddd"
	var str1 = "dddd"
	fmt.Println(str, str1)

	// 布尔类型
	var bool1 bool
	bool1 = true
	fmt.Println(bool1)
	fmt.Println("************* 推导类型 *************")

	// 推出类型 %T 大写的
	fmt.Printf("%T", str)
	fmt.Printf("%T", 123.6)
	fmt.Println("*************  转换类型 ************")

	var string1 string
	string1 = "123"
	fmt.Println(string1)

	// string =》 int
	fmt.Println("*************  string => int ************")
	num11, _ := strconv.Atoi(string1)
	fmt.Println(num11)

	fmt.Println("*************  string => int64 ************")
	num22, _ := strconv.ParseInt(string1, 10, 64)
	fmt.Println(num22)

	fmt.Println("*************  int => string ************")
	var num111 int = 99
	string111 := strconv.Itoa(num111)
	fmt.Println(string111)

	fmt.Println("*************  int64 => string ************")
	var num1112 int = 99999999
	string1112 := strconv.Itoa(num1112)
	fmt.Println(string1112)

	fmt.Println("************* string => float32  ************")
	var string32 = "1.34"
	float321, _ := strconv.ParseFloat(string32, 32)
	fmt.Println(float321)

	fmt.Println("************* string => float64  ************")
	var string64 = "1.341274878"
	float641, _ := strconv.ParseFloat(string64, 64)
	fmt.Println(float641)

	fmt.Println("************* int64 => int  ************")
	var num991 int64 = 2222
	num99 := int(num991)
	fmt.Println(num99)

	fmt.Println("************* int => int64  ************")
	var num992 int = 2222
	num999 := int64(num992)
	fmt.Println(num999)
}

// 第二节包引入
func demo2() {
	// 第二节
	fmt.Println("Hello World")
	//fmt.Println(cool.A)
	fmt.Println(A)
	fmt.Println(B)
	fmt.Println(dog.Name)
}
